package info.rflow;


import info.rflow.graph.RWorkflowScene;
import info.rflow.graph.model.DataEdge;
import info.rflow.graph.model.DataPin;
import info.rflow.graph.model.RBlockNode;
import info.rflow.model.RBlock;
import info.rflow.model.RFileParser;
import info.rflow.model.RWorkflowModel;
import info.rflow.preferences.GeneralSettings;
import info.rflow.util.GraphLayoutSerializer;
import org.netbeans.api.visual.widget.LabelWidget;

import javax.swing.*;
import java.io.File;
import java.util.ArrayList;


/**
 * DOCUMENT ME!
 *
 * @author Holger Brandl
 */
public class WorkflowContext {

    private RWorkflowScene workflowScene;
    private RWorkflowModel blockModel;

    private boolean isChanged = false;


    public WorkflowContext(File rFile) {
        this.workflowScene = new RWorkflowScene();

        if (rFile == null) {
            setBlockModel(new RWorkflowModel(null));
        } else {
            setBlockModel(RFileParser.readBlocks(rFile));
        }
    }


    public RWorkflowScene getWorkflowScene() {
        return workflowScene;
    }


    public File getLocation() {
        return blockModel.getRFile();
    }


    public void setLocation(File selectedFile) {
        blockModel.setRFile(selectedFile);
    }


    public boolean wasChanged() {
        return isChanged;
    }


    public void setChanged(boolean changed) {
        this.isChanged = changed;
    }


    public RWorkflowModel getModel() {
        return blockModel;
    }


    public void save() {
        save(blockModel.getRFile());
    }


    public void save(File saveFileName) {
        blockModel.save(saveFileName);
//        ConfigurationManagerUtils.save(cm, saveFileName);
        saveLayout(saveFileName);
    }


    public void saveLayout(File saveFileName) {
        GraphLayoutSerializer.saveLayout(workflowScene, Utils.getLayoutFile(saveFileName));
    }


    public void setBlockModel(RWorkflowModel blockModel) {
        assert blockModel != null;

        // clear graph
        for (RBlockNode rBlockNode : new ArrayList<RBlockNode>(workflowScene.getNodes())) {
            workflowScene.removeNodeWithEdges(rBlockNode);
        }

        for (LabelWidget labelWidget : new ArrayList<LabelWidget>(workflowScene.getBckndLabels())) {
            workflowScene.removeChild(labelWidget);
        }

        workflowScene.validate();

        // resetup the graph
        this.blockModel = blockModel;


        for (RBlock rBlock : blockModel.getBlocks()) {
            addNode(rBlock);
        }

        workflowScene.validate();

        // connect all nodes
        for (RBlock rBlock : blockModel.getBlocks()) {
            // first connect all input
            for (String inputName : rBlock.getInputs()) {
                // find the appropriate node
                RBlock blockByOutput = blockModel.getBlockByOutput(inputName);
                if (blockByOutput == null) {
//                    throw new RuntimeException("Can not find output for input: " + inputName);
                    System.err.println("Can not find output for input: " + inputName);
                }
                RBlockNode inputNode = workflowScene.findNodeByName(rBlock.getName());
                RBlockNode outputNode = workflowScene.findNodeByName(blockByOutput.getName());

                DataPin inputNodePin = inputNode.getInputPin();
                DataPin outputNodePin = outputNode.getOutputPin();
                workflowScene.createEdge(new DataEdge(outputNodePin, inputNodePin));
            }
        }

        workflowScene.validate();

        File layoutFile = Utils.getLayoutFile(blockModel.getRFile());
        if (layoutFile != null && layoutFile.isFile())
            GraphLayoutSerializer.loadLayout(workflowScene, layoutFile);
    }


    public RBlockNode addNode(RBlock rBlock) {

        RBlockNode node = new RBlockNode(rBlock);
        workflowScene.addNode(node);

        node.addInputPin(workflowScene);
        node.addOutputPin(workflowScene);

        return node;
    }


    public void syncGraphWithFile() {
        if (RFileParser.isUpToDate(blockModel)) {
            return;
        }


        // reload the graph

        String msg = "The script-file '" + blockModel.getRFile().getName() + "' has changed on your harddrive. \n" +
                "Do you want to reload it (and discard any changes)?";

        int status;
        if (Utils.getPrefs().getBoolean(GeneralSettings.AUTO_LOAD, GeneralSettings.AUTO_LOAD_DEFAULT)) {
            status = JOptionPane.YES_OPTION;
        } else {
            status = JOptionPane.showConfirmDialog(RFlow.getFrames()[0], msg, "Graph out of sync", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE);
        }

        if (status == JOptionPane.YES_OPTION) {
            if (getLocation() != null)
                setBlockModel(RFileParser.readBlocks(blockModel.getRFile()));
//                else
//                    saveWorkflowAs(workflowContext);
        }
    }
}
